<template>
  <div class="ai-assistant-container">
    <div class="page-header">
      <h1>AI 学习助手</h1>
      <p>智能问答，解决学习难题</p>
    </div>
    
    <div class="chat-container">
      <div class="chat-sidebar">
        <div class="history-header">
          <h3>历史对话</h3>
          <el-button type="primary" size="small" @click="createNewChat">
            <el-icon><Plus /></el-icon> 新对话
          </el-button>
        </div>
        
        <div class="chat-history">
          <div 
            v-for="(chat, index) in chatHistory" 
            :key="index"
            :class="['history-item', { active: currentChatId === chat.id }]"
            @click="selectChat(chat.id)"
          >
            <span class="chat-title">{{ chat.title }}</span>
            <span class="chat-time">{{ chat.time }}</span>
          </div>
        </div>
      </div>
      
      <div class="chat-main">
        <div class="message-list" ref="messageList">
          <div 
            v-for="(message, index) in currentMessages" 
            :key="index"
            :class="['message-item', message.role === 'assistant' ? 'ai-message' : 'user-message']"
          >
            <div class="message-avatar">
              <el-avatar :size="40" :src="message.role === 'assistant' ? aiAvatar : userAvatar"></el-avatar>
            </div>
            <div class="message-content">
              <div v-if="message.role === 'assistant'" v-html="formatMessage(message.content)"></div>
              <div v-else>{{ message.content }}</div>
              <div class="loading" v-if="message.loading">
                <div class="typing-indicator">
                  <span></span>
                  <span></span>
                  <span></span>
                </div>
              </div>
            </div>
          </div>
          
          <div v-if="isLoading && (!currentMessages.length || !currentMessages[currentMessages.length-1].loading)" class="message-item ai-message">
            <div class="message-avatar">
              <el-avatar :size="40" :src="aiAvatar"></el-avatar>
            </div>
            <div class="message-content">
              <div class="typing-indicator">
                <span></span>
                <span></span>
                <span></span>
              </div>
            </div>
          </div>
        </div>
        
        <div class="message-input">
          <!-- 将模型选择移到输入框上方 -->
          <div class="model-selector" v-if="modelList.length > 0">
            <el-select v-model="currentModel" placeholder="选择模型" size="small">
              <el-option
                v-for="model in modelList"
                :key="model"
                :label="model"
                :value="model"
              />
            </el-select>
          </div>
          
          <el-input
            v-model="userInput"
            type="textarea"
            :rows="3"
            placeholder="输入您的问题..."
            @keyup.enter.ctrl="sendMessage"
          ></el-input>
          <div class="input-actions">
            <span class="input-tip">按 Ctrl + Enter 发送</span>
            <el-button type="primary" @click="sendMessage" :disabled="!userInput.trim() || isLoading">
              发送
            </el-button>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, nextTick, watch } from 'vue';
import { useStore } from 'vuex';
import { Plus, CopyDocument } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { marked } from 'marked';
import hljs from 'highlight.js';
import 'highlight.js/styles/atom-one-dark.css'; // 使用深色主题
import { getModelList, sendChatMessage } from '@/api/ai/chat';
import katex from 'katex';
import 'katex/dist/katex.min.css';

const store = useStore();
const userInput = ref('');
const isLoading = ref(false);
const messageList = ref(null);
const currentChatId = ref(null);
const modelList = ref([]);
const currentModel = ref('');

// 配置 marked 渲染器，添加 LaTeX 支持
const renderer = new marked.Renderer();

// 重写 paragraph 方法，支持行内 LaTeX 和思考内容
renderer.paragraph = (text) => {
  // 处理思考内容 <think>content</think>
  text = text.replace(/<think>([\s\S]*?)<\/think>/g, (_, content) => {
    return `<div class="thinking-content">${content}</div>`;
  });
  
  // 处理行内 LaTeX: $formula$
  text = text.replace(/\$([^\$]+)\$/g, (_, formula) => {
    try {
      return katex.renderToString(formula, { throwOnError: false });
    } catch (e) {
      console.error('LaTeX 渲染错误:', e);
      return `<span class="latex-error">LaTeX Error: ${formula}</span>`;
    }
  });
  
  return `<p>${text}</p>`;
};

// 重写 codeBlock 方法，支持代码块中的 LaTeX 和添加复制按钮
renderer.code = (code, language) => {
  // 检查是否是 LaTeX 代码块
  if (language === 'latex' || language === 'math') {
    try {
      return `<div class="latex-block">${katex.renderToString(code, { 
        displayMode: true,
        throwOnError: false
      })}</div>`;
    } catch (e) {
      console.error('LaTeX 代码块渲染错误:', e);
      return `<pre><code class="latex-error">LaTeX Error: ${code}</code></pre>`;
    }
  }
  
  // 普通代码块使用 highlight.js 高亮并添加复制按钮
  let highlightedCode = '';
  if (language && hljs.getLanguage(language)) {
    try {
      highlightedCode = hljs.highlight(code, { language }).value;
    } catch (e) {
      console.error('代码高亮错误:', e);
      highlightedCode = hljs.highlightAuto(code).value;
    }
  } else {
    highlightedCode = hljs.highlightAuto(code).value;
  }
  
  // 添加复制按钮
  return `
    <div class="code-block-wrapper">
      <div class="code-header">
        <span class="code-language">${language || 'code'}</span>
        <button class="copy-button" onclick="navigator.clipboard.writeText(\`${code.replace(/`/g, '\\`')}\`).then(() => { alert('代码已复制到剪贴板'); })">
          <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
            <rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
            <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path>
          </svg>
          复制
        </button>
      </div>
      <pre><code class="hljs language-${language || ''}">${highlightedCode}</code></pre>
    </div>
  `;
};

// 配置 marked
marked.setOptions({
  renderer,
  highlight: function(code, lang) {
    if (lang && hljs.getLanguage(lang)) {
      return hljs.highlight(code, { language: lang }).value;
    }
    return hljs.highlightAuto(code).value;
  },
  breaks: true,
  gfm: true
});

// 头像
const userAvatar = 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png';
const aiAvatar = 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png';

// 本地存储聊天历史
const chatHistory = ref([]);

// 获取当前对话的消息
const currentMessages = computed(() => {
  if (!currentChatId.value) return [];
  const chat = chatHistory.value.find(c => c.id === currentChatId.value);
  return chat ? chat.messages : [];
});

// 创建新对话
const createNewChat = () => {
  const newChatId = 'chat_' + Date.now();
  const newChat = {
    id: newChatId,
    title: '新对话',
    time: new Date().toLocaleString(),
    messages: []
  };
  
  chatHistory.value.unshift(newChat);
  currentChatId.value = newChatId;
  
  // 保存到本地存储
  saveChatsToLocalStorage();
};

// 选择对话
const selectChat = (chatId) => {
  currentChatId.value = chatId;
};

// 添加消息
const addMessage = (chatId, message) => {
  const chat = chatHistory.value.find(c => c.id === chatId);
  if (chat) {
    chat.messages.push(message);
    
    // 如果是用户消息且是对话的第一条消息，更新对话标题
    if (message.role === 'user' && chat.messages.length === 1) {
      updateChatTitle(chatId, message.content);
    }
    
    // 保存到本地存储
    saveChatsToLocalStorage();
  }
};

// 更新对话标题
const updateChatTitle = (chatId, title) => {
  const chat = chatHistory.value.find(c => c.id === chatId);
  if (chat) {
    chat.title = title.length > 20 ? title.substring(0, 20) + '...' : title;
    chat.time = new Date().toLocaleString();
    
    // 保存到本地存储
    saveChatsToLocalStorage();
  }
};

// 保存聊天记录到本地存储
const saveChatsToLocalStorage = () => {
  localStorage.setItem('aiChatHistory', JSON.stringify(chatHistory.value));
};

// 从本地存储加载聊天记录
const loadChatsFromLocalStorage = () => {
  const savedChats = localStorage.getItem('aiChatHistory');
  if (savedChats) {
    try {
      chatHistory.value = JSON.parse(savedChats);
    } catch (e) {
      console.error('加载聊天记录失败:', e);
      chatHistory.value = [];
    }
  }
};

// 格式化消息（将 markdown 转为 html，并处理特殊格式）
const formatMessage = (content) => {
  // 移除末尾的 "end" 标记
  content = content.replace(/end$/, '');
  
  // 处理思考内容 <think>content</think>
  content = content.replace(/<think>([\s\S]*?)<\/think>/g, (_, thinkContent) => {
    return `<div class="thinking-content">${thinkContent}</div>`;
  });
  
  // 处理数学公式块: $$formula$$
  content = content.replace(/\$\$([\s\S]+?)\$\$/g, (_, formula) => {
    try {
      return katex.renderToString(formula, { 
        displayMode: true,
        throwOnError: false
      });
    } catch (e) {
      console.error('数学公式块渲染错误:', e);
      return `<div class="latex-error">LaTeX Error: ${formula}</div>`;
    }
  });
  
  // 处理 \boxed{} 格式的公式
  content = content.replace(/\\boxed\{([^}]+)\}/g, (_, formula) => {
    try {
      return katex.renderToString(`\\boxed{${formula}}`, { 
        displayMode: true,
        throwOnError: false
      });
    } catch (e) {
      console.error('Boxed 公式渲染错误:', e);
      return `<div class="latex-error">LaTeX Error: \\boxed{${formula}}</div>`;
    }
  });
  
  return marked(content);
};

// 滚动到底部
const scrollToBottom = () => {
  if (messageList.value) {
    messageList.value.scrollTop = messageList.value.scrollHeight;
  }
};

// 获取模型列表
const fetchModelList = async () => {
  try {
    const res = await getModelList();
    if (res && res.data) {
      modelList.value = res.data;
      console.log('获取到的模型列表:', modelList.value);
      if (modelList.value.length > 0) {
        currentModel.value = modelList.value[0];
      }
    }
  } catch (error) {
    console.error('获取模型列表失败:', error);
    ElMessage.error('获取模型列表失败，将使用默认模型');
  }
};

// 处理消息数据
const handleMessageData = (data) => {
  try {
    console.log('收到的原始数据:', data);
    
    // 移除末尾的 "end" 标记
    if (data === 'end') {
      return '';
    }
    
    // 尝试解析返回的数据
    let content = '';
    
    // 检查数据是否包含 JSON 对象序列
    if (data.includes('{"content":')) {
      // 尝试提取所有 content 字段
      const contentMatches = data.match(/\{"content":"([^"]*)"\}/g);
      if (contentMatches) {
        for (const match of contentMatches) {
          try {
            const parsed = JSON.parse(match);
            if (parsed.content) {
              content += parsed.content;
            }
          } catch (e) {
            console.warn('解析内容片段失败:', e);
          }
        }
      }
    } else {
      // 如果不是 JSON 格式，直接使用数据
      content = data;
    }
    
    console.log('提取的内容:', content);
    return content;
  } catch (e) {
    console.error('处理消息数据失败:', e);
    return data; // 出错时返回原始数据
  }
};

// 发送消息
const sendMessage = async () => {
  if (!userInput.value.trim() || isLoading.value) return;
  
  if (!currentChatId.value) {
    createNewChat();
  }
  
  const userMessage = {
    role: 'user',
    content: userInput.value
  };
  
  // 添加用户消息
  addMessage(currentChatId.value, userMessage);
  
  userInput.value = '';
  isLoading.value = true;
  
  // 滚动到底部
  await nextTick();
  scrollToBottom();
  
  try {
    // 创建 AI 响应消息
    const aiResponse = {
      role: 'assistant',
      content: '',
      loading: true
    };
    
    // 添加 AI 响应（初始为空，带 loading 状态）
    addMessage(currentChatId.value, aiResponse);
    
    // 调用 API 发送消息
    sendChatMessage(
      {
        model: currentModel.value || modelList.value[0]?.name || 'gpt-3.5-turbo',
        message: userMessage.content
      },
      // 消息回调
      (data) => {
        try {
          // 处理并提取内容
          const content = handleMessageData(data);
          
          // 如果是 end 标记，则移除 loading 状态
          if (data === 'end') {
            const chat = chatHistory.value.find(c => c.id === currentChatId.value);
            if (chat) {
              const aiMsg = chat.messages[chat.messages.length - 1];
              if (aiMsg && aiMsg.role === 'assistant') {
                aiMsg.loading = false;
                saveChatsToLocalStorage();
              }
            }
            return;
          }
          
          // 更新 AI 响应内容
          if (content) {
            const chat = chatHistory.value.find(c => c.id === currentChatId.value);
            if (chat) {
              const aiMsg = chat.messages[chat.messages.length - 1];
              if (aiMsg && aiMsg.role === 'assistant') {
                aiMsg.content += content;
                saveChatsToLocalStorage();
                
                // 滚动到底部
                nextTick(() => {
                  scrollToBottom();
                });
              }
            }
          }
        } catch (e) {
          console.error('处理消息流失败:', e);
        }
      },
      // 错误回调
      (error) => {
        console.error('发送消息错误:', error);
        ElMessage.error('发送消息失败，请重试');
        isLoading.value = false;
        
        // 更新最后一条消息，显示错误
        const chat = chatHistory.value.find(c => c.id === currentChatId.value);
        if (chat && chat.messages.length > 0) {
          const lastMsg = chat.messages[chat.messages.length - 1];
          if (lastMsg.role === 'assistant') {
            lastMsg.content += '\n\n**发送消息失败，请重试**';
            lastMsg.loading = false;
            saveChatsToLocalStorage();
          }
        }
      },
      // 完成回调
      () => {
        console.log('消息发送完成');
        isLoading.value = false;
        
        // 移除 loading 状态
        const chat = chatHistory.value.find(c => c.id === currentChatId.value);
        if (chat) {
          const aiMsg = chat.messages[chat.messages.length - 1];
          if (aiMsg && aiMsg.role === 'assistant') {
            aiMsg.loading = false;
            saveChatsToLocalStorage();
          }
        }
      }
    );
  } catch (error) {
    console.error('发送消息失败:', error);
    ElMessage.error('发送消息失败，请重试');
    isLoading.value = false;
  }
};

// 监听当前对话变化，滚动到底部
watch(currentMessages, () => {
  nextTick(() => {
    scrollToBottom();
  });
});

// 组件挂载时，加载聊天历史和模型列表
onMounted(async () => {
  // 加载聊天历史
  loadChatsFromLocalStorage();
  
  if (chatHistory.value.length > 0) {
    currentChatId.value = chatHistory.value[0].id;
  } else {
    createNewChat();
  }
  
  // 获取模型列表
  await fetchModelList();
  
  nextTick(() => {
    scrollToBottom();
  });
});
</script>

<style lang="scss" scoped>
.ai-assistant-container {
  padding: 20px;
  
  .page-header {
    margin-bottom: 20px;
    
    h1 {
      margin: 0 0 10px;
      font-size: 24px;
      color: #303133;
    }
    
    p {
      margin: 0;
      color: #606266;
    }
  }
  
  .chat-container {
    display: flex;
    height: calc(100vh - 150px);
    border: 1px solid #ebeef5;
    border-radius: 4px;
    overflow: hidden;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    
    .chat-sidebar {
      width: 250px;
      display: flex;
      flex-direction: column;
      border-right: 1px solid #ebeef5;
      background-color: #f5f7fa;
      
      .history-header {
        padding: 15px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        border-bottom: 1px solid #e6e6e6;
        
        h3 {
          margin: 0;
          font-size: 16px;
        }
      }
      
      .chat-history {
        flex: 1;
        overflow-y: auto;
        
        .history-item {
          padding: 12px 15px;
          cursor: pointer;
          border-bottom: 1px solid #ebeef5;
          transition: background-color 0.3s;
          
          &:hover {
            background-color: #ecf5ff;
          }
          
          &.active {
            background-color: #ecf5ff;
            border-right: 3px solid #409eff;
          }
          
          .chat-title {
            display: block;
            font-size: 14px;
            color: #303133;
            margin-bottom: 5px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
          
          .chat-time {
            font-size: 12px;
            color: #909399;
          }
        }
      }
    }
    
    .chat-main {
      flex: 1;
      display: flex;
      flex-direction: column;
      background-color: #fff;
      
      .message-list {
        flex: 1;
        overflow-y: auto;
        padding: 20px;
        
        .message-item {
          display: flex;
          margin-bottom: 20px;
          
          .message-avatar {
            margin-right: 12px;
            flex-shrink: 0;
          }
          
          .message-content {
            max-width: 85%; /* 增加消息宽度 */
            padding: 12px 16px;
            border-radius: 8px;
            font-size: 14px;
            line-height: 1.5;
            
            :deep(.thinking-content) {
              font-size: 12px;
              color: #909399;
              background-color: #f8f8f8;
              padding: 8px;
              border-radius: 4px;
              margin: 8px 0;
              border-left: 3px solid #dcdfe6;
            }
            
            :deep(.katex-display) {
              margin: 1em 0;
              overflow-x: auto;
              overflow-y: hidden;
            }
            
            :deep(.latex-block) {
              margin: 1em 0;
              overflow-x: auto;
            }
            
            :deep(.latex-error) {
              color: #f56c6c;
              background-color: #fef0f0;
              padding: 5px;
              border-radius: 4px;
            }
            
            :deep(.code-block-wrapper) {
              margin: 1em 0;
              border-radius: 6px;
              overflow: hidden;
              
              .code-header {
                display: flex;
                justify-content: space-between;
                align-items: center;
                background-color: #343a40;
                padding: 8px 12px;
                color: #e9ecef;
                
                .code-language {
                  font-size: 12px;
                  font-weight: 500;
                  text-transform: uppercase;
                }
                
                .copy-button {
                  background: none;
                  border: none;
                  color: #e9ecef;
                  cursor: pointer;
                  display: flex;
                  align-items: center;
                  gap: 4px;
                  font-size: 12px;
                  padding: 4px 8px;
                  border-radius: 4px;
                  
                  &:hover {
                    background-color: #495057;
                  }
                  
                  svg {
                    width: 14px;
                    height: 14px;
                  }
                }
              }
              
              pre {
                margin: 0;
                padding: 12px;
                background-color: #0a265f;
                overflow-x: auto;
                
                code {
                  font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
                  font-size: 13px;
                }
              }
            }
            
            :deep(pre) {
              background-color: #282c34;
              padding: 12px;
              border-radius: 4px;
              overflow-x: auto;
              margin: 1em 0;
              
              code {
                color: #abb2bf;
              }
            }
            
            :deep(code) {
              font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
            }
            
            :deep(p) {
              margin: 8px 0;
            }
            
            :deep(blockquote) {
              border-left: 4px solid #dfe2e5;
              padding-left: 1em;
              margin-left: 0;
              color: #606266;
            }
            
            :deep(table) {
              border-collapse: collapse;
              margin: 1em 0;
              width: 100%;
              
              th, td {
                border: 1px solid #dcdfe6;
                padding: 8px 12px;
              }
              
              th {
                background-color: #f5f7fa;
              }
            }
            
            :deep(img) {
              max-width: 100%;
            }
            
            .loading {
              margin-top: 8px;
            }
          }
          
          &.user-message {
            flex-direction: row-reverse;
            
            .message-avatar {
              margin-right: 0;
              margin-left: 12px;
            }
            
            .message-content {
              background-color: #ecf5ff;
              color: #303133;
            }
          }
          
          &.ai-message {
            .message-content {
              background-color: #f5f7fa;
              color: #303133;
            }
          }
        }
        
        .typing-indicator {
          display: flex;
          align-items: center;
          
          span {
            height: 8px;
            width: 8px;
            border-radius: 50%;
            background-color: #909399;
            margin: 0 2px;
            display: inline-block;
            animation: typing 1.5s infinite ease-in-out;
            
            &:nth-child(1) {
              animation-delay: 0s;
            }
            
            &:nth-child(2) {
              animation-delay: 0.2s;
            }
            
            &:nth-child(3) {
              animation-delay: 0.4s;
            }
          }
        }
      }
      
      .message-input {
        padding: 15px;
        border-top: 1px solid #ebeef5;
        
        .model-selector {
          margin-bottom: 10px;
          
          .el-select {
            width: 200px;
          }
        }
        
        .input-actions {
          display: flex;
          justify-content: space-between;
          align-items: center;
          margin-top: 10px;
          
          .input-tip {
            font-size: 12px;
            color: #909399;
          }
        }
      }
    }
  }
}

@keyframes typing {
  0% {
    transform: translateY(0);
  }
  50% {
    transform: translateY(-5px);
  }
  100% {
    transform: translateY(0);
  }
}

@media (max-width: 768px) {
  .chat-container {
    flex-direction: column;
    height: calc(100vh - 150px);
    
    .chat-sidebar {
      width: 100%;
      height: 200px;
    }
  }
}
</style>